home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -serious- / programming / other / dopus412-gpl / dopus_disk / format.c < prev    next >
C/C++ Source or Header  |  2000-02-28  |  23KB  |  899 lines

  1. /*
  2.  
  3. Directory Opus 4
  4. Original GPL release version 4.12
  5. Copyright 1993-2000 Jonathan Potter
  6.  
  7. This program is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU General Public License
  9. as published by the Free Software Foundation; either version 2
  10. of the License, or (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20.  
  21. All users of Directory Opus 4 (including versions distributed
  22. under the GPL) are entitled to upgrade to the latest version of
  23. Directory Opus version 5 at a reduced price. Please see
  24. http://www.gpsoft.com.au for more information.
  25.  
  26. The release of Directory Opus 4 under the GPL in NO WAY affects
  27. the existing commercial status of Directory Opus 5.
  28.  
  29. */
  30.  
  31. #include "diskop.h"
  32.  
  33. #define FORMATFLAG_FFS             1
  34. #define FORMATFLAG_INTERNATIONAL   2
  35. #define FORMATFLAG_CACHING         4
  36. #define FORMATFLAG_TRASHCAN        8
  37. #define FORMATFLAG_VERIFY         16
  38.  
  39. enum {
  40.     FORMAT_NAME,
  41.     FORMAT_FFS,
  42.     FORMAT_INTERNATIONAL,
  43.     FORMAT_CACHING,
  44.     FORMAT_TRASHCAN,
  45.     FORMAT_VERIFY,
  46.     FORMAT_FORMAT,
  47.     FORMAT_QUICKFORMAT,
  48.     FORMAT_CANCEL};
  49.  
  50. struct TagItem
  51.     format_name_gadget[]={
  52.         {RO_Type,OBJECT_GADGET},
  53.         {RO_GadgetType,GADGET_STRING},
  54.         {RO_GadgetID,FORMAT_NAME},
  55.         {RO_Left,19},
  56.         {RO_Width,21},
  57.         {RO_Height,1},
  58.         {RO_TextNum,STR_FORMAT_NAME},
  59.         {RO_TextPos,TEXTPOS_LEFT},
  60.         {RO_StringLen,31},
  61.         {TAG_END,0}},
  62.     format_ffs_gadget[]={
  63.         {RO_Type,OBJECT_GADGET},
  64.         {RO_GadgetType,GADGET_CHECK},
  65.         {RO_GadgetID,FORMAT_FFS},
  66.         {RO_Left,14},
  67.         {RO_Top,2},
  68.         {RO_TextNum,STR_FORMAT_FFS},
  69.         {RO_TextPos,TEXTPOS_RIGHT},
  70.         {TAG_END,0}},
  71.     format_international_gadget[]={
  72.         {RO_Type,OBJECT_GADGET},
  73.         {RO_GadgetType,GADGET_CHECK},
  74.         {RO_GadgetID,FORMAT_INTERNATIONAL},
  75.         {RO_Left,14},
  76.         {RO_Top,3},
  77.         {RO_TopFine,5},
  78.         {RO_TextNum,STR_FORMAT_INTERNATIONAL},
  79.         {RO_TextPos,TEXTPOS_RIGHT},
  80.         {TAG_END,0}},
  81.     format_caching_gadget[]={
  82.         {RO_Type,OBJECT_GADGET},
  83.         {RO_GadgetType,GADGET_CHECK},
  84.         {RO_GadgetID,FORMAT_CACHING},
  85.         {RO_Left,14},
  86.         {RO_Top,4},
  87.         {RO_TopFine,10},
  88.         {RO_TextNum,STR_FORMAT_CACHING},
  89.         {RO_TextPos,TEXTPOS_RIGHT},
  90.         {TAG_END,0}},
  91.     format_trashcan_gadget[]={
  92.         {RO_Type,OBJECT_GADGET},
  93.         {RO_GadgetType,GADGET_CHECK},
  94.         {RO_GadgetID,FORMAT_TRASHCAN},
  95.         {RO_Left,14},
  96.         {RO_Top,5},
  97.         {RO_TopFine,15},
  98.         {RO_TextNum,STR_FORMAT_TRASHCAN},
  99.         {RO_TextPos,TEXTPOS_RIGHT},
  100.         {TAG_END,0}},
  101.     format_verify_gadget[]={
  102.         {RO_Type,OBJECT_GADGET},
  103.         {RO_GadgetType,GADGET_CHECK},
  104.         {RO_GadgetID,FORMAT_VERIFY},
  105.         {RO_Left,14},
  106.         {RO_Top,6},
  107.         {RO_TopFine,20},
  108.         {RO_TextNum,STR_FORMAT_VERIFY},
  109.         {RO_TextPos,TEXTPOS_RIGHT},
  110.         {RO_BoolOn,TRUE},
  111.         {TAG_END,0}},
  112.     format_format_gadget[]={
  113.         {RO_Type,OBJECT_GADGET},
  114.         {RO_GadgetType,GADGET_BOOLEAN},
  115.         {RO_GadgetID,FORMAT_FORMAT},
  116.         {RO_Top,8},
  117.         {RO_TopFine,37},
  118.         {RO_Width,13},
  119.         {RO_Height,1},
  120.         {RO_HeightFine,4},
  121.         {RO_TextNum,STR_FORMAT_FORMAT},
  122.         {RO_TextPos,TEXTPOS_CENTER},
  123.         {RO_HighRecess,TRUE},
  124.         {TAG_END,0}},
  125.     format_quickformat_gadget[]={
  126.         {RO_Type,OBJECT_GADGET},
  127.         {RO_GadgetType,GADGET_BOOLEAN},
  128.         {RO_GadgetID,FORMAT_QUICKFORMAT},
  129.         {RO_Left,14},
  130.         {RO_Top,8},
  131.         {RO_TopFine,37},
  132.         {RO_Width,13},
  133.         {RO_Height,1},
  134.         {RO_HeightFine,4},
  135.         {RO_TextNum,STR_FORMAT_QUICKFORMAT},
  136.         {RO_TextPos,TEXTPOS_CENTER},
  137.         {RO_HighRecess,TRUE},
  138.         {TAG_END,0}},
  139.     format_cancel_gadget[]={
  140.         {RO_Type,OBJECT_GADGET},
  141.         {RO_GadgetType,GADGET_BOOLEAN},
  142.         {RO_GadgetID,FORMAT_CANCEL},
  143.         {RO_Left,28},
  144.         {RO_Top,8},
  145.         {RO_TopFine,37},
  146.         {RO_Width,13},
  147.         {RO_Height,1},
  148.         {RO_HeightFine,4},
  149.         {RO_TextNum,STR_FORMAT_EXIT},
  150.         {RO_TextPos,TEXTPOS_CENTER},
  151.         {RO_HighRecess,TRUE},
  152.         {TAG_END,0}},
  153.  
  154.     format_device_list[]={
  155.         {RO_Type,OBJECT_LISTVIEW},
  156.         {RO_ListViewID,0},
  157.         {RO_LeftFine,2},
  158.         {RO_Width,10},
  159.         {RO_Height,6},
  160.         {RO_HeightFine,30},
  161.         {RO_HighRecess,TRUE},
  162.         {TAG_END,0}},
  163.  
  164.     format_info_box[]={
  165.         {RO_Type,OBJECT_BORDER},
  166.         {RO_BorderType,BORDER_RECESSED},
  167.         {RO_LeftFine,2},
  168.         {RO_Top,7},
  169.         {RO_TopFine,28},
  170.         {RO_Width,41},
  171.         {RO_WidthFine,-4},
  172.         {RO_Height,1},
  173.         {RO_HeightFine,4},
  174.         {TAG_END,0}},
  175.         
  176.     *format_gadgets[]={
  177.         format_name_gadget,
  178.         format_ffs_gadget,
  179.         format_international_gadget,
  180.         format_caching_gadget,
  181.         format_trashcan_gadget,
  182.         format_verify_gadget,
  183.         format_format_gadget,
  184.         format_quickformat_gadget,
  185.         format_cancel_gadget,
  186.         NULL};
  187.  
  188. void diskop_format(vis,portname,argc,argv)
  189. struct VisInfo *vis;
  190. char *portname;
  191. int argc;
  192. char *argv[];
  193. {
  194.     struct RequesterBase formatreq;
  195.     struct Window *window;
  196.     struct IntuiMessage *msg;
  197.     Object_Border *infobox;
  198.     struct DOpusListView *devicelist,*view;
  199.     struct Gadget *gadlist,*gad,*gad_international=NULL,*gad_caching=NULL;
  200.     ULONG class,mask,flags;
  201.     USHORT code,gadgetid;
  202.     APTR iaddress;
  203.     struct StringExtend stringex;
  204.     char *diskname;
  205.     int a,b,gadcount=0,ignorechange=0;
  206.     int start=-1,quick=0,startflags=FORMATFLAG_TRASHCAN;
  207.  
  208.     formatreq.rb_width=41;
  209.     formatreq.rb_height=9;
  210.     formatreq.rb_widthfine=16;
  211.     formatreq.rb_heightfine=54;
  212.     formatreq.rb_leftoffset=8;
  213.     formatreq.rb_topoffset=8;
  214.     formatreq.rb_flags=0;
  215.  
  216.     fill_out_req(&formatreq,vis);
  217.  
  218.     formatreq.rb_privateflags=0;
  219.     formatreq.rb_screenname=NULL;
  220.  
  221.     if (formatreq.rb_screen && !(vis->vi_flags&VISF_BORDERS)) {
  222.         formatreq.rb_flags|=RBF_STRINGS;
  223.         formatreq.rb_title=NULL;
  224.     }
  225.     else {
  226.         formatreq.rb_flags|=RBF_BORDERS|RBF_CLOSEGAD|RBF_STRINGS;
  227.         formatreq.rb_title=string_table[STR_FORMAT_FORMAT];
  228.     }
  229.  
  230.     formatreq.rb_extend=&stringex;
  231.     formatreq.rb_idcmpflags=0;
  232.     formatreq.rb_string_table=string_table;
  233.  
  234.     for (a=0;a<2;a++) {
  235.         stringex.Pens[a]=vis->vi_stringcol[a];
  236.         stringex.ActivePens[a]=vis->vi_activestringcol[a];
  237.     }
  238.     stringex.InitialModes=0;
  239.     stringex.EditHook=NULL;
  240.     stringex.WorkBuffer=NULL;
  241.     for (a=0;a<4;a++) stringex.Reserved[a]=0;
  242.  
  243.     if (SysBase->LibNode.lib_Version<39) mask=12;
  244.     else mask=0;
  245.  
  246.     if (!(window=OpenRequester(&formatreq)) ||
  247.         !(gadlist=addreqgadgets(&formatreq,format_gadgets,mask,&gadcount)) ||
  248.         !(infobox=(Object_Border *)
  249.             AddRequesterObject(&formatreq,format_info_box)) ||
  250.         !(devicelist=(struct DOpusListView *)
  251.             AddRequesterObject(&formatreq,format_device_list)) ||
  252.         !(devicelist->items=get_device_list(&formatreq.rb_memory,NULL))) {
  253.         CloseRequester(&formatreq);
  254.         return;
  255.     }
  256.  
  257.     fix_listview(&formatreq,devicelist);
  258.     select_device(devicelist,NULL);
  259.  
  260.     diskname=((struct StringInfo *)gadlist->SpecialInfo)->Buffer;
  261.     strcpy(diskname,string_table[STR_FORMAT_EMPTY]);
  262.  
  263.     get_env("format",gadlist,gadcount,devicelist);
  264.  
  265.     flags=0;
  266.     gad=gadlist;
  267.     for (a=0;a<gadcount;a++) {
  268.         if (gad->Activation&GACT_TOGGLESELECT)
  269.             if (gad->Flags&GFLG_SELECTED) flags|=1<<(gad->GadgetID-1);
  270.         gad->Flags&=~GFLG_DISABLED;
  271.         gad=gad->NextGadget;
  272.     }
  273.  
  274.     if (SysBase->LibNode.lib_Version>38) {
  275.         gad_international=gadlist->NextGadget->NextGadget;
  276.         gad_caching=gad_international->NextGadget;
  277.     }
  278.  
  279.     for (a=0;a<argc;a++) {
  280.         if (LStrCmpI(argv[a],"quick")==0) quick=1;
  281.         else if (LStrCmpI(argv[a],"ffs")==0) startflags|=FORMATFLAG_FFS;
  282.         else if (LStrCmpI(argv[a],"cache")==0) startflags|=FORMATFLAG_CACHING;
  283.         else if (LStrnCmpI(argv[a],"inter",5)==0) startflags|=FORMATFLAG_INTERNATIONAL;
  284.         else if (LStrCmpI(argv[a],"noicons")==0) startflags&=~FORMATFLAG_TRASHCAN;
  285.         else if (LStrCmpI(argv[a],"verify")==0) startflags|=FORMATFLAG_VERIFY;
  286.         else {
  287.             if (start==-1) {
  288.                 for (b=0;devicelist->items[b];b++) {
  289.                     if (LStrCmpI(argv[a],devicelist->items[b])==0) {
  290.                         start=b;
  291.                         devicelist->itemselected=b;
  292.                         break;
  293.                     }
  294.                 }
  295.             }
  296.             else LStrnCpy(diskname,argv[a],30);
  297.         }
  298.     }
  299.  
  300.     if (start>-1) {
  301.         gad=gadlist;
  302.         for (a=0;a<gadcount;a++) {
  303.             if (startflags&(1<<(gad->GadgetID-1))) gad->Flags|=GFLG_SELECTED;
  304.             else gad->Flags&=~GFLG_SELECTED;
  305.             gad=gad->NextGadget;
  306.         }
  307.     }
  308.  
  309.     RefreshRequesterObject(&formatreq,NULL);
  310.     RefreshGList(gadlist,window,NULL,gadcount);
  311.  
  312.     if (flags&FORMATFLAG_CACHING && gad_international) {
  313.         flags|=FORMATFLAG_INTERNATIONAL;
  314.         gad_international->Flags|=GFLG_SELECTED;
  315.         RefreshGList(gad_international,window,NULL,1);
  316.         DisableGadget(gad_international,window->RPort,0,0);
  317.     }
  318.  
  319.     if (!(AddListView(devicelist,1))) {
  320.         CloseRequester(&formatreq);
  321.         return;
  322.     }
  323.     show_sel_item(devicelist);
  324.     show_device_info(&formatreq,infobox,devicelist->items[devicelist->itemselected]);
  325.  
  326.     if (start>-1) {
  327.         if (do_format(&formatreq,
  328.             infobox,
  329.             devicelist->items[start],
  330.             diskname,
  331.             startflags,
  332.             quick))
  333.             dopus_message(DOPUSMSG_UPDATEDRIVE,(APTR)devicelist->items[start],portname);
  334.         RemoveListView(devicelist,1);
  335.         CloseRequester(&formatreq);
  336.         return;
  337.     }
  338.  
  339.     FOREVER {
  340.         while (msg=(struct IntuiMessage *)GetMsg(window->UserPort)) {
  341.             if ((view=(struct DOpusListView *)ListViewIDCMP(devicelist,msg))==
  342.                 (struct DOpusListView *)-1) {
  343.                 class=msg->Class; code=msg->Code;
  344.                 iaddress=msg->IAddress;
  345.                 ReplyMsg((struct Message *)msg);
  346.  
  347.                 switch (class) {
  348.                     case IDCMP_DISKINSERTED:
  349.                     case IDCMP_DISKREMOVED:
  350.                         if (ignorechange) ignorechange=0;
  351.                         else {
  352.                             show_device_info(&formatreq,
  353.                                 infobox,
  354.                                 devicelist->items[devicelist->itemselected]);
  355.                         }
  356.                         break;
  357.  
  358.                     case IDCMP_VANILLAKEY:    
  359.                         a=0;
  360.                         code=toupper(code);
  361.                         switch (code) {
  362.                             case 'N':
  363.                                 ActivateStrGad(gadlist,window);
  364.                                 break;
  365.                             case 'F':
  366.                                 a=1;
  367.                                 flags^=FORMATFLAG_FFS;
  368.                                 break;
  369.                             case 'I':
  370.                                 if (SysBase->LibNode.lib_Version>38) {
  371.                                     a=2;
  372.                                     flags^=FORMATFLAG_INTERNATIONAL;
  373.                                 }
  374.                                 break;
  375.                             case 'D':
  376.                                 if (SysBase->LibNode.lib_Version>38) {
  377.                                     a=3;
  378.                                     flags^=FORMATFLAG_CACHING;
  379.                                 }
  380.                                 break;
  381.                             case 'P':
  382.                                 if (SysBase->LibNode.lib_Version>38) a=4;
  383.                                 else a=2;
  384.                                 flags^=FORMATFLAG_TRASHCAN;
  385.                                 break;
  386.                             case 'V':
  387.                                 if (SysBase->LibNode.lib_Version>38) a=5;
  388.                                 else a=3;
  389.                                 flags^=FORMATFLAG_VERIFY;
  390.                                 break;
  391.  
  392.                             case 0x1b:
  393.                                 set_env("format",gadlist,gadcount,devicelist);
  394.                                 RemoveListView(devicelist,1);
  395.                                 CloseRequester(&formatreq);
  396.                                 return;
  397.                         }
  398.                         if (a) {
  399.                             gad=gadlist;
  400.                             while (a-- && gad->NextGadget) gad=gad->NextGadget;
  401.                             gad->Flags^=GFLG_SELECTED;
  402.                             RefreshGList(gad,window,NULL,1);
  403.                             if (gad==gad_international) {
  404.                                 gad_caching->Flags&=~GFLG_SELECTED;
  405.                                 RefreshGList(gad_caching,window,NULL,1);
  406.                                 flags&=~FORMATFLAG_CACHING;
  407.                             }
  408.                             else if (gad==gad_caching) {
  409.                                 gad_international->Flags&=~GFLG_SELECTED;
  410.                                 RefreshGList(gad_international,window,NULL,1);
  411.                                 flags&=~FORMATFLAG_INTERNATIONAL;
  412.                             }
  413.                         }
  414.                         break;
  415.  
  416.                     case IDCMP_GADGETDOWN:
  417.                     case IDCMP_GADGETUP:
  418.                         gadgetid=((struct Gadget *)iaddress)->GadgetID;
  419.                     case IDCMP_CLOSEWINDOW:
  420.                         if (class==IDCMP_CLOSEWINDOW) gadgetid=FORMAT_CANCEL;
  421.  
  422.                         switch (gadgetid) {
  423.                             case FORMAT_FFS:
  424.                                 flags^=FORMATFLAG_FFS;
  425.                                 break;
  426.  
  427.                             case FORMAT_INTERNATIONAL:
  428.                                 flags^=FORMATFLAG_INTERNATIONAL;
  429.                                 flags&=~FORMATFLAG_CACHING;
  430.                                 gad_caching->Flags&=~GFLG_SELECTED;
  431.                                 RefreshGList(gad_caching,window,NULL,1);
  432.                                 break;
  433.  
  434.                             case FORMAT_CACHING:
  435.                                 flags^=FORMATFLAG_CACHING;
  436.                                 if (flags&FORMATFLAG_CACHING) {
  437.                                     flags|=FORMATFLAG_INTERNATIONAL;
  438.                                     gad_international->Flags|=GFLG_SELECTED;
  439.                                     RefreshGList(gad_international,window,NULL,1);
  440.                                     DisableGadget(gad_international,window->RPort,0,0);
  441.                                 }
  442.                                 else EnableGadget(gad_international,window->RPort,0,0);
  443.                                 break;
  444.  
  445.                             case FORMAT_TRASHCAN:
  446.                                 flags^=FORMATFLAG_TRASHCAN;
  447.                                 break;
  448.  
  449.                             case FORMAT_VERIFY:
  450.                                 flags^=FORMATFLAG_VERIFY;
  451.                                 break;
  452.  
  453.                             case FORMAT_CANCEL:
  454.                                 set_env("format",gadlist,gadcount,devicelist);
  455.                                 RemoveListView(devicelist,1);
  456.                                 CloseRequester(&formatreq);
  457.                                 return;
  458.  
  459.                             case FORMAT_FORMAT:
  460.                             case FORMAT_QUICKFORMAT:
  461.                                 if (do_format(&formatreq,
  462.                                     infobox,
  463.                                     devicelist->items[devicelist->itemselected],
  464.                                     diskname,
  465.                                     flags,
  466.                                     (gadgetid==FORMAT_QUICKFORMAT))) {
  467.                                     ignorechange=1;
  468.                                     dopus_message(DOPUSMSG_UPDATEDRIVE,
  469.                                         (APTR)devicelist->items[devicelist->itemselected],
  470.                                         portname);
  471.                                 }
  472.                                 break;
  473.                         }
  474.                         break;
  475.                 }
  476.             }
  477.             else if (view) show_device_info(&formatreq,infobox,view->items[view->itemselected]);
  478.         }
  479.         Wait(1<<window->UserPort->mp_SigBit);
  480.     }
  481. }
  482.  
  483. void show_device_info(reqbase,border,name)
  484. struct RequesterBase *reqbase;
  485. Object_Border *border;
  486. char *name;
  487. {
  488.     struct DeviceNode *devnode;
  489.     struct DosEnvec *dosenvec;
  490.     int tracks,tracksize,size;
  491.     char infobuf[60],sizebuf[20];
  492.  
  493.     border_text(reqbase,border,NULL);
  494.  
  495.     if (!name || !(devnode=find_device(name))) return;
  496.  
  497.     dosenvec=(struct DosEnvec *)
  498.         BADDR(((struct FileSysStartupMsg *)BADDR(devnode->dn_Startup))->fssm_Environ);
  499.  
  500.     tracks=dosenvec->de_HighCyl-dosenvec->de_LowCyl+1;
  501.     tracksize=(dosenvec->de_BlocksPerTrack*dosenvec->de_Surfaces)*(dosenvec->de_SizeBlock*4);
  502.     size=tracks*tracksize;
  503.  
  504.     getsizestring(sizebuf,size);
  505.     lsprintf(infobuf,string_table[STR_FORMAT_INFODISPLAY],tracks,tracksize,sizebuf);
  506.  
  507.     border_text(reqbase,border,infobuf);
  508. }
  509.  
  510. void getsizestring(buf,a)
  511. char *buf;
  512. ULONG a;
  513. {
  514.     a/=1024;
  515.     if (a>1073741824) lsprintf(buf,"HUGE");
  516.     else if (a>1048576) {
  517.         getfloatstr((double)((double)a/1048576),buf);
  518.         LStrCat(buf,"G");
  519.     }
  520.     else if (a>1024) {
  521.         getfloatstr((double)((double)a/1024),buf);
  522.         LStrCat(buf,"M");
  523.     }
  524.     else lsprintf(buf,"%ldK",a);
  525. }
  526.  
  527. void getfloatstr(f,buf)
  528. double f;
  529. char *buf;
  530. {
  531.     int a,b,c,d;
  532.     char buf1[20];
  533.  
  534.     a=(int)f; f-=a;
  535.     b=(int)(f*100);
  536.     c=(b/10)*10; d=b-c;
  537.     if (d>4) c+=10;
  538.     if (c==100) {
  539.         c=0; ++a;
  540.     }
  541.     lsprintf(buf1,"%ld",c); buf1[1]=0;
  542.     lsprintf(buf,"%ld.%s",a,buf1);
  543. }
  544.  
  545. do_format(reqbase,border,device,name,flags,quick)
  546. struct RequesterBase *reqbase;
  547. Object_Border *border;
  548. char *device,*name;
  549. ULONG flags;
  550. char quick;
  551. {
  552.     ULONG dostype;
  553.     struct DeviceHandle handle;
  554.     int suc=1,txt=STR_FAILED_ERROR;
  555.     struct Requester busyreq;
  556.  
  557.     if (flags&FORMATFLAG_INTERNATIONAL) {
  558.         if (flags&FORMATFLAG_FFS) dostype=ID_INTER_FFS_DISK;
  559.         else dostype=ID_INTER_DOS_DISK;
  560.     }
  561.     else if (flags&FORMATFLAG_CACHING) {
  562.         if (flags&FORMATFLAG_FFS) dostype=ID_FASTDIR_FFS_DISK;
  563.         else dostype=ID_FASTDIR_DOS_DISK;
  564.     }
  565.     else if (flags&FORMATFLAG_FFS) dostype=ID_FFS_DISK;
  566.     else dostype=ID_DOS_DISK;
  567.  
  568.     if (!(open_device(device,&handle))) txt=STR_NODEVICE_ERROR;
  569.     else {
  570.         InitRequester(&busyreq);
  571.         busyreq.Flags=NOISYREQ;
  572.         Request(&busyreq,reqbase->rb_window);
  573.         SetBusyPointer(reqbase->rb_window);
  574.  
  575.         border_text(reqbase,border,string_table[STR_CHECKING_DESTINATION]);
  576.  
  577.         if (check_disk(reqbase,handle.device_req,device,1)) {
  578.             if (check_blank_disk(reqbase,device,string_table[STR_FORMAT_FORMAT])) {
  579.  
  580.                 suc=0;
  581.  
  582.                 inhibit_drive(device,DOSTRUE);
  583.                 drive_motor(handle.device_req,1);
  584.  
  585.                 if (!quick) {
  586.                     suc=do_raw_format(reqbase,border,
  587.                         handle.device_req,
  588.                         (handle.dosenvec->de_SizeBlock<<2)*
  589.                             handle.dosenvec->de_Surfaces*handle.dosenvec->de_BlocksPerTrack,
  590.                         handle.dosenvec->de_LowCyl,
  591.                         handle.dosenvec->de_HighCyl-handle.dosenvec->de_LowCyl+1,
  592.                         handle.dosenvec->de_BufMemType,
  593.                         flags);
  594.                 }
  595.  
  596.                 if (!suc) {
  597.                     border_text(reqbase,border,string_table[STR_FORMAT_INITIALISING]);
  598.  
  599.                     if (DOSBase->dl_lib.lib_Version>36) {
  600.                         if (Format(device,name,dostype)) suc=0;
  601.                         else suc=ERROR_FAILED;
  602.                     }
  603.                     else {
  604.                         suc=do_initialise(handle.device_req,name,dostype,
  605.                             handle.dosenvec->de_LowCyl*
  606.                                 handle.dosenvec->de_BlocksPerTrack*
  607.                                 handle.dosenvec->de_Surfaces,
  608.                             (handle.dosenvec->de_HighCyl-handle.dosenvec->de_LowCyl+1)*
  609.                                 handle.dosenvec->de_BlocksPerTrack*handle.dosenvec->de_Surfaces,
  610.                             handle.dosenvec->de_Reserved,
  611.                             handle.dosenvec->de_BufMemType,
  612.                             flags);
  613.                     }
  614.                 }
  615.  
  616.                 drive_motor(handle.device_req,0);
  617.                 inhibit_drive(device,FALSE);
  618.  
  619.                 switch (suc) {
  620.                     case 0:
  621.                         if (flags&FORMATFLAG_TRASHCAN) {
  622.                             if (SysBase->LibNode.lib_Version<36) Delay(150);
  623.                             write_trashcan(reqbase,border,device);
  624.                         }
  625.                         txt=STR_SUCCESS;
  626.                         break;
  627.                     case ERROR_FAILED: txt=STR_FAILED_ERROR; break;
  628.                     case ERROR_MEMORY: txt=STR_MEMORY_ERROR; break;
  629.                     case ERROR_BITMAP: txt=STR_BITMAP_ERROR; break;
  630.                     case ERROR_ABORTED: txt=STR_ABORTED; break;
  631.                     case ERROR_VERIFY: txt=-1; break;
  632.                     default: txt=STR_DEVICE_ERROR; break;
  633.                 }
  634.             }
  635.             else txt=STR_ABORTED;
  636.         }
  637.         else txt=STR_ABORTED;
  638.  
  639.         EndRequest(&busyreq,reqbase->rb_window);
  640.         ClearPointer(reqbase->rb_window);
  641.     }
  642.  
  643.     close_device(&handle);
  644.     if (txt>-1) border_text(reqbase,border,string_table[txt]);
  645.     return((txt==STR_SUCCESS));
  646. }
  647.  
  648. do_initialise(device_req,name,dostype,firstblock,numblocks,reserved,memtype,flags)
  649. struct IOExtTD *device_req;
  650. char *name;
  651. ULONG dostype;
  652. ULONG firstblock,numblocks,reserved;
  653. ULONG memtype;
  654. ULONG flags;
  655. {
  656.     ULONG *bitmap,bitmapsize;
  657.     char *buffer;
  658.     struct BitmapBlock *bitmapblock;
  659.     struct BitmapExtension *bitmapextension;
  660.     struct RootDirectory *rootdirectory;
  661.     struct DOpusRemember *key=NULL;
  662.     LONG error,a;
  663.     LONG bitmapcount,bitmapblocks;
  664.     LONG count,root;
  665.     LONG extensioncount,extensionblocks=0;
  666.  
  667.     bitmapsize=(numblocks-reserved+31)/32;
  668.  
  669.     if (!(buffer=LAllocRemember(&key,TD_SECTOR,memtype|MEMF_PUBLIC|MEMF_CLEAR)))
  670.         return(ERROR_MEMORY);
  671.  
  672.     *(ULONG *)buffer=dostype;
  673.  
  674.     for (a=0;a<2;a++) {
  675.         if (error=do_writeblock(device_req,buffer,firstblock+a)) {
  676.             LFreeRemember(&key);
  677.             return(error);
  678.         }
  679.         *(ULONG *)buffer=0;
  680.     }
  681.  
  682.     if (!(bitmap=(ULONG *)LAllocRemember(&key,sizeof(ULONG)*bitmapsize,MEMF_PUBLIC))) {
  683.         LFreeRemember(&key);
  684.         return(ERROR_MEMORY);
  685.     }
  686.  
  687.     for (a=0;a<bitmapsize;a++) bitmap[a]=~0;
  688.  
  689.     count=bitmapblocks=(bitmapsize+126)/127;
  690.  
  691.     if (count>25) {
  692.         if (!(flags&FORMATFLAG_FFS)) {
  693.             LFreeRemember(&key);
  694.             return(ERROR_BITMAP);
  695.         }
  696.         count-=25;
  697.  
  698.         do {
  699.             ++extensionblocks;
  700.  
  701.             if (count>127) count-=127;
  702.             else count=0;
  703.         }
  704.         while (count);
  705.     }
  706.  
  707.     root=numblocks>>1;
  708.     rootdirectory=(struct RootDirectory *)buffer;
  709.     for (a=0;a<TD_SECTOR;a++) buffer[a]=0;
  710.  
  711.     rootdirectory->PrimaryType=2;
  712.     rootdirectory->HashTableSize=128-56;
  713.     rootdirectory->BitmapFlag=DOSTRUE;
  714.     DateStamp(&rootdirectory->LastRootChange);
  715.  
  716.     if ((a=strlen(name))>31) a=31;
  717.  
  718.     rootdirectory->DiskName[0]=a;
  719.     CopyMem(name,&rootdirectory->DiskName[1],a);
  720.  
  721.     DateStamp(&rootdirectory->LastDiskChange);
  722.     DateStamp(&rootdirectory->CreationDate);
  723.  
  724.     rootdirectory->SecondaryType=1;
  725.  
  726.     for (a=0;a<bitmapblocks;a++) {
  727.         if (a==25) break;
  728.         rootdirectory->BitmapPointers[a]=root+firstblock+a+1;
  729.     }
  730.  
  731.     if (bitmapblocks>25) rootdirectory->BitmapExtension=root+firstblock+26;
  732.     rootdirectory->Checksum=-do_checksum((ULONG *)rootdirectory);
  733.  
  734.     if (error=do_writeblock(device_req,rootdirectory,root+firstblock)) {
  735.         LFreeRemember(&key);
  736.         return(error);
  737.     }
  738.  
  739.     for (a=root-reserved;a<root-reserved+bitmapblocks+extensionblocks+1;a++)
  740.         bitmap[a/32]&=BitTable[a%32];
  741.  
  742.     bitmapblock=(struct BitmapBlock *)buffer;
  743.  
  744.     for (a=0;a<bitmapblocks;a++) {
  745.         CopyMem(&bitmap[a*127],&bitmapblock->Bitmap[0],sizeof(ULONG)*127);
  746.         bitmapblock->Checksum=0;
  747.         bitmapblock->Checksum=-do_checksum((ULONG *)bitmapblock);
  748.         if (error=do_writeblock(device_req,bitmapblock,root+firstblock+a+1)) {
  749.             LFreeRemember(&key);
  750.             return(error);
  751.         }
  752.     }
  753.  
  754.     if (extensionblocks) {
  755.         bitmapextension=(struct BitmapExtension *)buffer;
  756.  
  757.         bitmapcount=root+firstblock+1;
  758.         extensioncount=bitmapcount+bitmapblocks;
  759.         bitmapblocks-=25;
  760.  
  761.         while (bitmapblocks) {
  762.             for (a=0;a<TD_SECTOR;a++) buffer[a]=0;
  763.             for (a=0;a<(bitmapblocks<127?bitmapblocks:127);a++)
  764.                 bitmapextension->BitmapPointers[a]=bitmapcount++;
  765.             if (bitmapblocks>127) bitmapblocks-=127;
  766.             else bitmapblocks=0;
  767.  
  768.             if (bitmapblocks) bitmapextension->BitmapExtension=extensioncount+1;
  769.             if (error=do_writeblock(device_req,bitmapextension,extensioncount++)) {
  770.                 LFreeRemember(&key);
  771.                 return(error);
  772.             }
  773.         }
  774.     }
  775.  
  776.     LFreeRemember(&key);
  777.     return(0);
  778. }
  779.  
  780. do_raw_format(reqbase,border,device_req,tracksize,lowtrack,numtracks,memtype,flags)
  781. struct RequesterBase *reqbase;
  782. Object_Border *border;
  783. struct IOExtTD *device_req;
  784. ULONG tracksize,lowtrack,numtracks;
  785. ULONG memtype;
  786. ULONG flags;
  787. {
  788.     ULONG *trackbuffer,*verifybuffer;
  789.     struct DOpusRemember *key=NULL;
  790.     ULONG offset;
  791.     int track,a,cmpsize,ret;
  792.     char infobuf[80];
  793.  
  794.     if (!(trackbuffer=(ULONG *)LAllocRemember(&key,tracksize,memtype|MEMF_CLEAR)))
  795.         return(ERROR_MEMORY);
  796.     if (flags&FORMATFLAG_VERIFY) {
  797.         verifybuffer=(ULONG *)LAllocRemember(&key,tracksize,memtype);
  798.         cmpsize=tracksize>>2;
  799.     }
  800.     else verifybuffer=NULL;
  801.  
  802.     offset=lowtrack*tracksize;
  803.  
  804.     for (track=0;track<numtracks;track++) {
  805.         lsprintf(infobuf,string_table[STR_FORMAT_FORMATTING],track,numtracks-track-1);
  806.         border_text(reqbase,border,infobuf);
  807.  
  808.         FOREVER {
  809.             if (check_abort(reqbase->rb_window)) {
  810.                 LFreeRemember(&key);
  811.                 return(ERROR_ABORTED);
  812.             }
  813.  
  814.             device_req->iotd_Req.io_Command=TD_FORMAT;
  815.             device_req->iotd_Req.io_Data=(APTR)trackbuffer;
  816.             device_req->iotd_Req.io_Offset=offset;
  817.             device_req->iotd_Req.io_Length=tracksize;
  818.  
  819.             if (!(DoIO((struct IORequest *)device_req))) {
  820.                 if (!verifybuffer) break;
  821.                 device_req->iotd_Req.io_Command=CMD_UPDATE;
  822.                 if (!(DoIO((struct IORequest *)device_req))) break;
  823.             }
  824.  
  825.             lsprintf(infobuf,string_table[STR_FORMAT_FORMATERROR],track);
  826.             border_text(reqbase,border,infobuf);
  827.             if (!(check_error(reqbase,infobuf,STR_RETRY))) {
  828.                 LFreeRemember(&key);
  829.                 return(ERROR_FAILED);
  830.             }
  831.         }
  832.  
  833.         if (verifybuffer) {
  834.             lsprintf(infobuf,string_table[STR_FORMAT_VERIFYING],track,numtracks-track-1);
  835.             border_text(reqbase,border,infobuf);
  836.  
  837.             FOREVER {
  838.                 if (check_abort(reqbase->rb_window)) {
  839.                     LFreeRemember(&key);
  840.                     return(ERROR_ABORTED);
  841.                 }
  842.  
  843.                 device_req->iotd_Req.io_Command=CMD_READ;
  844.                 device_req->iotd_Req.io_Data=(APTR)verifybuffer;
  845.                 device_req->iotd_Req.io_Offset=offset;
  846.                 device_req->iotd_Req.io_Length=tracksize;
  847.  
  848.                 if (!(DoIO((struct IORequest *)device_req))) {
  849.                     for (a=0;a<cmpsize;a++) {
  850.                         if (verifybuffer[a]!=0) break;
  851.                     }
  852.                     if (a==cmpsize) break;
  853.                     lsprintf(infobuf,string_table[STR_FORMAT_VERIFYERROR],track);
  854.                     ret=ERROR_VERIFY;
  855.                 }
  856.                 else {
  857.                     lsprintf(infobuf,string_table[STR_FORMAT_FORMATERROR],track);
  858.                     ret=ERROR_FAILED;
  859.                 }
  860.  
  861.                 border_text(reqbase,border,infobuf);
  862.                 if (!(check_error(reqbase,infobuf,STR_RETRY))) {
  863.                     LFreeRemember(&key);
  864.                     return(ret);
  865.                 }
  866.             }
  867.         }
  868.  
  869.         offset+=tracksize;
  870.     }
  871.     LFreeRemember(&key);
  872.     return(0);
  873. }
  874.  
  875. void write_trashcan(reqbase,border,device)
  876. struct RequesterBase *reqbase;
  877. Object_Border *border;
  878. char *device;
  879. {
  880.     struct DiskObject *trashcan;
  881.     BPTR lock;
  882.     char name[80];
  883.  
  884.     if (!IconBase) return;
  885.  
  886.     border_text(reqbase,border,string_table[STR_FORMAT_MAKINGTRASHCAN]);
  887.  
  888.     lsprintf(name,"%sTrashcan",device);
  889.     if (!(lock=CreateDir(name))) return;
  890.     UnLock(lock);
  891.  
  892.     if (IconBase->lib_Version>36 &&
  893.         (trashcan=GetDefDiskObject(WBGARBAGE))) {
  894.         PutDiskObject(name,trashcan);
  895.         FreeDiskObject(trashcan);
  896.     }
  897.     else PutDiskObject(name,&trashcanicon_icon);
  898. }
  899.